package ipmsg.etc;

import ipmsg.file.ConfigAddedUsers;
import ipmsg.file.ConfigBlacklist;
import ipmsg.file.Configuration;
import ipmsg.gui.MsgWindow;
import ipmsg.network.UtilityNet;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Vector;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class GlobalVar {
    public static String USER_NAME;
    public static String HOST_NAME;
    public static char SEND_MSG_STYLE;
    public static String CHARACTER_ENCODING;
    public static char THEME;
    public static int LOG_MAX_LEN;
    public static String USER_HOME;
    public static String NEW_LINE;
    public static String FILE_PATH_DELIMITER;
    public static char OS;
    public static Vector<String> ALL_IP_ADDRESS = new Vector<>();
    public static Semaphore COMMAND_QUEUE_EMPTY = new Semaphore(100);
    public static Semaphore COMMAND_QUEUE_fULL = new Semaphore(0);

    public static void init() {
        initSystemVar();
        Configuration.readConfig();
        ConfigBlacklist.readConfig();
        ConfigAddedUsers.readConfig();
    }

    public static void initDefault() {
        USER_NAME = System.getProperty("user.name");
        try {
            if (OS == '\001')
                HOST_NAME = USER_NAME;
            else {
                HOST_NAME = InetAddress.getLocalHost().getHostName();
            }
        } catch (UnknownHostException ex) {
        }
        SEND_MSG_STYLE = '\000';
        CHARACTER_ENCODING = "GB2312";
        THEME = '\000';
        LOG_MAX_LEN = 1000;
    }

    private static void initSystemVar() {
        USER_HOME = System.getProperty("user.home");
        NEW_LINE = System.getProperty("line.separator");
        FILE_PATH_DELIMITER = System.getProperty("file.separator");

        if (System.getProperty("os.name").equalsIgnoreCase("linux")) {
            OS = '\000';
        } else if (System.getProperty("os.name").startsWith("Windows")) {
            OS = '\001';
        } else {
            OS = '\002';
        }

        UtilityNet.refreshMyIps();
    }

    private static LinkedList<Command> COMMAND_QUEUE = new LinkedList<Command>();
    private static final Lock COMMAND_QUEUE_Lock = new ReentrantLock();

    public static void pushCommand(Command com) {
        COMMAND_QUEUE_Lock.lock();
        COMMAND_QUEUE.add(com);
        COMMAND_QUEUE_Lock.unlock();
    }

    public static Command popCommand() {
        COMMAND_QUEUE_Lock.lock();
        Command com = COMMAND_QUEUE.removeFirst();
        COMMAND_QUEUE_Lock.unlock();
        return com;
    }

    private static LinkedList<User> USER_LIST = new LinkedList<User>();
    private static final Lock USER_LIST_Lock = new ReentrantLock();

    public static void addUser(String ip, String name, String group, String host) {
        USER_LIST_Lock.lock();

        User usr;
        if ((usr = getUser(ip)) == null) {
            USER_LIST.add(new User(ip, name, group, host));
        } else {
            usr.setName(name);
            usr.setGroup(group);
            usr.setHost(host);
        }
        USER_LIST_Lock.unlock();
    }

    public static void delUser(String ip) {
        USER_LIST_Lock.lock();
        Iterator<User> it = USER_LIST.iterator();
        while (it.hasNext()) {
            User obj = it.next();
            if (obj.getIp().equals(ip))
                it.remove();
        }
        USER_LIST_Lock.unlock();
    }

    public static User getUser(String ip) {
        USER_LIST_Lock.lock();
        User res = null;
        Iterator<User> it = USER_LIST.iterator();
        while (it.hasNext()) {
            User obj = it.next();
            if (obj.getIp().equals(ip)) {
                res = obj;
                break;
            }
        }
        USER_LIST_Lock.unlock();
        return res;
    }

    public static Vector<String> getUserList() {
        USER_LIST_Lock.lock();
        Vector<String> res = new Vector<String>();
        Iterator<User> it = USER_LIST.iterator();
        while (it.hasNext()) {
            User obj = it.next();
            res.add(obj.getIp());
        }
        USER_LIST_Lock.unlock();
        return res;
    }

    public static void clearUsers() {
        USER_LIST_Lock.lock();
        USER_LIST.clear();
        USER_LIST_Lock.unlock();
    }

    private static HashMap<String, MsgWindow> MSG_WINDOW_REG = new HashMap<String, MsgWindow>();

    private static final Lock MSG_WINDOW_REG_Lock = new ReentrantLock();

    public static void addWindow(String id, MsgWindow win) {
        MSG_WINDOW_REG_Lock.lock();
        MSG_WINDOW_REG.put(id, win);
        MSG_WINDOW_REG_Lock.unlock();
    }

    public static void delWindow(String id) {
        MSG_WINDOW_REG_Lock.lock();
        MSG_WINDOW_REG.remove(id);
        MSG_WINDOW_REG_Lock.unlock();
    }

    public static boolean containWindow(String id) {
        MSG_WINDOW_REG_Lock.lock();
        boolean res;
        if (MSG_WINDOW_REG.containsKey(id))
            res = true;
        else
            res = false;
        MSG_WINDOW_REG_Lock.unlock();
        return res;
    }

    public static MsgWindow getWindow(String id) {
        MSG_WINDOW_REG_Lock.lock();
        MsgWindow res;
        if (!MSG_WINDOW_REG.containsKey(id))
            res = null;
        else
            res = (MsgWindow) MSG_WINDOW_REG.get(id);
        MSG_WINDOW_REG_Lock.unlock();
        return res;
    }

    public static Vector<String> WINDOW_REG = new Vector<String>();

    public static Vector<String> ADDED_USER = new Vector<String>();

    public static Vector<String> BLACK_LIST = new Vector<String>();

    private static LinkedList<FileLinkList> FILE_LIST = new LinkedList<FileLinkList>();
    private static final Lock FILE_LIST_Lock = new ReentrantLock();

    public static FileLinkList getFileList(int packetNo) {
        FILE_LIST_Lock.lock();
        FileLinkList res = null;
        Iterator<FileLinkList> it = FILE_LIST.iterator();
        while (it.hasNext()) {
            res = (FileLinkList) it.next();
            if (res.getPacketNo() == packetNo) {
                break;
            }
        }
        FILE_LIST_Lock.unlock();
        return res;
    }

    public static void addFileList(FileLinkList flist) {
        FILE_LIST_Lock.lock();
        FileLinkList res = null;
        Iterator<FileLinkList> it = FILE_LIST.iterator();
        while (it.hasNext()) {
            res = (FileLinkList) it.next();
            if (res.getPacketNo() == flist.getPacketNo()) {
                break;
            }
            res = null;
        }

        if (res == null) {
            FILE_LIST.add(flist);
        }
        FILE_LIST_Lock.unlock();
    }

    public static void delFileList(int packetNo) {
        FILE_LIST_Lock.lock();
        FileLinkList res = null;
        Iterator<FileLinkList> it = FILE_LIST.iterator();
        while (it.hasNext()) {
            res = (FileLinkList) it.next();
            if (res.getPacketNo() == packetNo) {
                it.remove();
            }
        }

        FILE_LIST_Lock.unlock();
    }

    public static void delFileList(String StrPacketNo) {
        int packetNo;
        try {
            packetNo = Integer.parseInt(StrPacketNo);
        } catch (NumberFormatException e) {
            return;
        }
        FILE_LIST_Lock.lock();
        FileLinkList res = null;
        Iterator<FileLinkList> it = FILE_LIST.iterator();
        while (it.hasNext()) {
            res = it.next();
            if (res.getPacketNo() == packetNo) {
                it.remove();
            }
        }

        FILE_LIST_Lock.unlock();
    }

    public static Vector<String> exportPacketNo() {
        FILE_LIST_Lock.lock();
        Vector<String> res = new Vector<String>();
        FileLinkList tmp = null;
        Iterator<FileLinkList> it = FILE_LIST.iterator();
        while (it.hasNext()) {
            tmp = it.next();
            res.add(tmp.getPacketNo() + "");
        }
        FILE_LIST_Lock.unlock();
        return res;
    }

}
